<template>
  <div style="border: 1px solid #ccc">
    <input
      type="file"
      accept=".docx,.pdf"
      id="editorWordFileId"
      ref="fileInput"
      @change="uploadFile"
      style="display: none"
    />
    <Toolbar
      style="border-bottom: 1px solid #ccc"
      :editor="editor"
      :defaultConfig="toolbarConfig"
      :mode="mode"
    />
    <Editor
      :style="{ height: height }"
      style="overflow: auto"
      v-model="htmlValue"
      :defaultConfig="editorConfig"
      :mode="mode"
      @onCreated="onCreated"
      @onBlur="onBlur"
    />
  </div>
</template>

<script>
import "@wangeditor/editor/dist/css/style.css";
import { Editor, Toolbar, } from "@wangeditor/editor-for-vue";
import { uploadOSS, fammterString } from "@/api/upload";
import { base64ToFile } from "@/utils/base64ToFile";
import axios from "axios";
import "@/plugins/editor-plugins";

// 常量定义
const IMAGE_TYPES = /\.(gif|jpg|jpeg|png|bmp)$/i;
const VIDEO_TYPES = /\.(mp4|avi|wmv|rmvb|flv|mkv)$/i;
const MAX_IMAGE_SIZE = 10 * 1024 * 1024; // 10MB
const MAX_VIDEO_SIZE = 500 * 1024 * 1024; // 500MB

let scrollContainer = null; // 存储实际滚动容器
export default {
  name: "WangEditor",
  components: { Editor, Toolbar },
  props: {
    action: String,
    uuid: {
      type: [String, Number],
      default: "",
    },
    height: {
      type: [String],
      default: "300px",
    },
    isgetIndex: {
      type: [String, Number],
      default: "0",
    },
    placeholder: {
      type: String,
      default: "请输入正文",
    },
    editorValue: {
      type: String,
      default: "",
    },
  },
  data() {
    return {
      questionElements: [],
      editor: null,
      htmlValue: "<p></p>",
      loadingInstance: null,
      toolbarConfig: this.getToolbarConfig(),
      editorConfig: {
        placeholder: this.placeholder,
        MENU_CONF: {
          uploadImage: {
            customUpload: this.uploadImage,
          },
          uploadVideo: {
            customUpload: this.uploadVideo,
          },
        },
      },
      mode: "default", // or 'simple'
    };
  },
  watch: {
    placeholder(newValue) {
      this.editorConfig.placeholder = newValue;
    },
    isgetIndex(newValue) {
      this.toolbarConfig.toolbarKeys = this.getToolbarKeys(newValue);
    },
    editorValue: {
      handler(newValue) {
        console.log('Updated htmlValue:', newValue);
        // 只有当内容确实发生变化且编辑器不处于焦点状态时才更新
        if (newValue !== this.htmlValue) {
          this.htmlValue = newValue;
        }
      },
    },
    htmlValue(newValue) {
      if (this.editorValue !== newValue) {
        const processedHtml = this.processEditorHtml(newValue);
        this.$emit("update:editorValue", processedHtml);
      }
      // 获取编辑器DOM容器
      this.$nextTick(() => {
        if (this.editor && this.isgetIndex == 3) {
          this.editor.focus();
          //   this.editor.selection = null; // 安全重置
          const editorDom = this.editor.getEditableContainer();
          scrollContainer = editorDom.querySelector(".w-e-scroll");
          let questionElements = [];
          const paragraphs = editorDom.querySelectorAll("p");
          paragraphs.forEach((p, index) => {
            const text = p.textContent.trim();
            // 匹配：数字 + . + 空格? + 【  开头
            const match = text.match(/^(\d+)\.\s*【/);
            if (match) {
              console.log(match);
              const questionIndex = parseInt(match[1]) - 1; // 题号从 0 开始
              questionElements.push({
                index: questionIndex,
                element: p,
                top: p.offsetTop,
              });
            }
          });
          questionElements.map((item, index) => {
            item.index = index;
          });

          this.questionElements = questionElements;
          console.log("questionElements", questionElements);
        }
      });
    },
  },
  methods: {
    // 获取工具栏配置
    getToolbarConfig() {
      return {
        toolbarKeys: this.getToolbarKeys(this.isgetIndex),
      };
    },

    // 根据模式获取工具栏键
    getToolbarKeys(mode) {
      const commonKeys = [
        "headerSelect",
        "blockquote",
        "through",
        "code",
        "sup",
        "sub",
        "clearStyle",
        "bold",
        "underline",
        "italic",
        "color",
        "bgColor",
        "fontSize",
        "fontFamily",
        "lineHeight",
        "bulletedList",
        "numberedList",
        "todo",
        "justifyLeft",
        "justifyRight",
        "justifyCenter",
        "justifyJustify",
        "indent",
        "delIndent",
        "insertLink",
        "insertTable",
        "codeBlock",
        "divider",
        "undo",
        "redo",
        "fullScreen",
      ];
      if (mode == 1) {
        return ["uploadImage", ...commonKeys];
      } else if (mode == 2) {
        return ["uploadImage", "uploadVideo", "kityFormula", ...commonKeys];
      } else if (mode == 3) {
        console.log(1111);
        return [
          "uploadImage",
          "uploadVideo",

          "kityFormula",

          "sup",
          "sub",
          "clearStyle",
          "bold",
          "underline",
          "italic",
          "color",
          "bgColor",
          "fontSize",
          "fontFamily",

          "bulletedList",

          "justifyLeft",
          "justifyRight",
          "justifyCenter",
          "justifyJustify",
          "indent",
          "delIndent",
          "insertLink",
          "insertTable",

          "undo",
          "redo",
        ];
      } else {
        return [
          "uploadImage",
          "uploadVideo",
          "upLoadWord",
          "kityFormula",
          ...commonKeys,
        ];
      }
    },
    onBlur(e) {
      this.$emit("Blur", true);
    },
    insert(htmlContent) {
      console.log("先确保编辑器有焦点", this.editor.isFocused());

      // 先确保编辑器有焦点
      this.editor.focus();

      setTimeout(() => {
        this.editor.restoreSelection();
        this.editor.dangerouslyInsertHtml(htmlContent);
      }, 100);
    },
    scrollToId(elemId) {
      console.log("elemId", elemId);
      const container = this.editor.getEditableContainer();
      const paragraphs = container.querySelectorAll("p");
      // 找到包含 "1.【单选题】" 的段落
      for (let p of paragraphs) {
        if (p.textContent.includes(`${elemId}.【`)) {
          p.scrollIntoView({ behavior: "smooth" });
          break;
        }
      }
    },

    // 编辑器创建回调
    onCreated(editor) {
      this.editor = Object.seal(editor);
      this.htmlValue = this.editorValue;
      setTimeout(() => {
        editor.focus(true);
      }, 300);
      editor.on("scroll", () => {
        if (this.action == "left") {
          const scrollTop = scrollContainer.scrollTop;
          let currentIndex = 0;

          // 遍历 questionElements，找最后一个 top <= scrollTop 的题
          for (let i = 0; i < this.questionElements.length; i++) {
            const { top, index } = this.questionElements[i];

            if (scrollTop >= top - 50) {
              // -1 防止浮点误差
              currentIndex = index;
            } else {
              // 由于 questionElements 按 top 升序排列，后面的 top 更大，直接退出
              break;
            }
          }

          console.log("当前滚动到题号索引:", currentIndex + 1);
          this.$emit("scroll", currentIndex + 1); // 打印 0 开始的 index
        }
      });
    },
    // 处理编辑器HTML
    processEditorHtml(html) {
      return html
        .replace(/<img(?=\s)/g, '<img class="editor_img"')
        .replace(/<video(?=\s)/g, '<video class="wangeditor_video" controlsList="nodownload"');
    },

    // 上传图片
    async uploadImage(file, insertFn) {
      if (!this.validateFile(file, IMAGE_TYPES, MAX_IMAGE_SIZE, "图片")) {
        return false;
      }

      try {
        const path = fammterString(2, this.uuid);
        const res = await uploadOSS(file, path);
        insertFn(res[0]);
      } catch (error) {
        this.handleUploadError(error, "图片上传失败");
      }
    },

    // 上传视频
    async uploadVideo(file, insertFn) {
      if (!this.validateFile(file, VIDEO_TYPES, MAX_VIDEO_SIZE, "视频")) {
        return false;
      }

      try {
        const path = fammterString(2, this.uuid);
        const res = await uploadOSS(file, path);
        insertFn(res[0]);
      } catch (error) {
        this.handleUploadError(error, "视频上传失败");
      }
    },

    // 文件验证
    validateFile(file, typeRegex, maxSize, fileType) {
      if (!typeRegex.test(file.name)) {
        this.$modal.msgWarning(`${fileType}类型不合法`);
        return false;
      }

      if (file.size > maxSize) {
        this.$modal.msgWarning(
          `${fileType}大小不能超过${maxSize / 1024 / 1024}MB`
        );
        return false;
      }

      return true;
    },

    // 处理文件选择
    uploadFile(event) {
      const file = event.target.files[0];
      if (!file) return;

      if (file.type === "application/pdf") {
        this.handlePdfUpload(file);
      } else {
        this.handleWordUpload(file);
      }

      event.target.value = "";
    },

    // 处理PDF上传
    async handlePdfUpload(file) {
      this.showLoading("上传处理中,请稍等…(0%)");

      try {
        const pdfData = await this.readFileAsArrayBuffer(file);
        const pdfUrl = URL.createObjectURL(
          new Blob([pdfData], { type: "application/pdf" })
        );
        const result = await this.convertPdfToImages(pdfUrl);

        this.updateLoading("上传处理中,请稍等…(100%)");
        this.$emit("turnWord", result);
      } catch (error) {
        this.handleUploadError(error, "PDF处理失败");
      } finally {
        this.closeLoading();
      }
    },

    // 处理Word上传
    handleWordUpload(file) {
      this.showLoading("上传处理中,请稍等…(0%)");

      const formData = new FormData();
      formData.append("file", file);

      axios
        .post("https://hgcc.metaxun.com/node/upload", formData, {
          onUploadProgress: (e) => {
            if (e.lengthComputable) {
              const progress = Math.min(
                99,
                Math.floor((e.loaded / e.total) * 100)
              );
              this.updateLoading(`上传处理中,请稍等…(${progress}%)`);
            }
          },
        })
        .then(async (res) => {
          if (res.data.code === 200) {
            const processedContent = await this.processWordContent(
              res.data.htmlData
            );
            this.$emit("turnWord", processedContent);
            this.updateLoading("上传处理中,请稍等…(100%)");
          } else {
            this.$modal.msgError(res.data.msg || "上传失败");
          }
        })
        .catch(this.handleUploadError)
        .finally(this.closeLoading);
    },

    // 读取文件为ArrayBuffer
    readFileAsArrayBuffer(file) {
      return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.onload = () => resolve(reader.result);
        reader.onerror = reject;
        reader.readAsArrayBuffer(file);
      });
    },

    // 转换PDF为图片
    async convertPdfToImages(pdfUrl) {
      const pdf = await pdfjsLib.getDocument(pdfUrl).promise;
      const numPages = pdf.numPages;
      let result = "";

      for (let pageNumber = 1; pageNumber <= numPages; pageNumber++) {
        const page = await pdf.getPage(pageNumber);
        const viewport = page.getViewport({ scale: 1 });
        const canvas = document.createElement("canvas");
        const context = canvas.getContext("2d");

        canvas.height = viewport.height;
        canvas.width = viewport.width;

        await page.render({ canvasContext: context, viewport }).promise;

        const imageData = canvas.toDataURL("image/png");
        const base64Data = imageData.match(
          /data:image\/[^;]+;base64,([^">]+)/
        )[1];
        const file = base64ToFile(base64Data, "editor_image.png", "image/png");
        const res = await uploadOSS(file);

        result += `<img src="${res[0]}" alt="Page ${pageNumber}" />`;
      }

      return result;
    },

    // 处理Word内容
    async processWordContent(content) {
      const imgRegex =
        /<img[^>]+src="data:image\/[^;]+;base64,([^">]+)"[^>]*>/g;
      const imgTags = content.match(imgRegex);

      if (!imgTags) return content;

      let processedContent = content;

      for (const imgTag of imgTags) {
        const base64Data = imgTag.match(/data:image\/[^;]+;base64,([^">]+)/)[1];
        const file = base64ToFile(base64Data, "editor_image.png", "image/png");
        const res = await uploadOSS(file);
        processedContent = processedContent.replace(
          imgTag,
          `<img src="${res[0]}" />`
        );
      }
      processedContent = processedContent.replace(
        /(<td[^>]*>)([\s\S]*?)(<img[^>]*>)([\s\S]*?)(<\/td>)/gi,
        (match, tdOpen, beforeImg, imgTag, afterImg, tdClose) => {
          // 移除p标签
          const removePTags = (str) => str.replace(/<\/?p[^>]*>/g, "");
          // 处理前后换行
          const processedBefore = beforeImg.trim()
            ? removePTags(beforeImg) + "<br>"
            : "";
          const processedAfter = afterImg.trim()
            ? "<br>" + removePTags(afterImg)
            : "";

          return tdOpen + processedBefore + imgTag + processedAfter + tdClose;
        }
      );
      return processedContent;
    },

    // 显示加载状态
    showLoading(text) {
      this.loadingInstance = this.$loading({
        lock: true,
        text: text,
        spinner: "el-icon-loading",
        background: "rgba(255, 255, 255, 0.3)",
      });
    },

    // 更新加载状态
    updateLoading(text) {
      if (this.loadingInstance) {
        this.loadingInstance.setText(text);
      }
    },

    // 关闭加载状态
    closeLoading() {
      if (this.loadingInstance) {
        this.loadingInstance.close();
        this.loadingInstance = null;
      }
    },

    // 处理上传错误
    handleUploadError(error, defaultMsg = "上传失败") {
      if (error.response) {
        this.$modal.msgError(error.response.data.msg || defaultMsg);
      } else if (error.request) {
        console.error("请求已发送但无响应:", error.request);
        this.$modal.msgError("服务器异常");
      } else {
        console.error("请求错误:", error.message);
        this.$modal.msgError(defaultMsg);
      }
    },

    // 触发文件选择
    triggerFileInput() {
      this.$refs.fileInput.click();
    },
  },
  beforeDestroy() {
    if (this.editor) {
      this.editor.destroy();
      this.editor = null;
    }
    this.closeLoading();
  },
};
</script>
<style>
.wangeditor_video{
  max-width: 100%;
  height: auto;
}
video{
  max-width: 100%;
  height: auto;
}
</style>
<style scoped lang="scss">
::v-deep .w-e-select-list ul {
  margin: 0 !important;
  list-style-type: none !important;
}
.w-e-full-screen-container {
  z-index: 3;
}
</style>
